package com.cloudcc.mobile.im;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;

import com.cloudcc.cloudframe.util.LogUtils;
import com.cloudcc.mobile.AppManager;
import com.cloudcc.mobile.R;
import com.cloudcc.mobile.entity.CoworkerEntity;
import com.cloudcc.mobile.im.domain.InviteMessage;
import com.cloudcc.mobile.im.domain.InviteMessage.InviteMesageStatus;
import com.cloudcc.mobile.im.parse.UserProfileManager;
import com.cloudcc.mobile.im.receiver.CallReceiver;
import com.cloudcc.mobile.im.ui.ChatActivity;
import com.cloudcc.mobile.im.ui.VideoCallActivity;
import com.cloudcc.mobile.im.ui.VoiceCallActivity;
import com.cloudcc.mobile.im.utils.PreferenceManager;
import com.cloudcc.mobile.manager.ContactsManager;
import com.cloudcc.mobile.manager.RunTimeManager;
import com.cloudcc.mobile.util.ToastUtil;
import com.cloudcc.mobile.view.im.ConversationListActivity;
import com.cloudcc.mobile.view.main.MainUIActivity;
import com.cloudcc.mobile.view.wel.WelcomeActivity;
import com.easemob.EMCallBack;
import com.easemob.EMConnectionListener;
import com.easemob.EMError;
import com.easemob.EMEventListener;
import com.easemob.EMGroupChangeListener;
import com.easemob.EMNotifierEvent;
import com.easemob.EMValueCallBack;
import com.easemob.chat.CmdMessageBody;
import com.easemob.chat.EMChat;
import com.easemob.chat.EMChatManager;
import com.easemob.chat.EMChatOptions;
import com.easemob.chat.EMContactManager;
import com.easemob.chat.EMGroup;
import com.easemob.chat.EMGroupManager;
import com.easemob.chat.EMMessage;
import com.easemob.chat.EMMessage.ChatType;
import com.easemob.chat.EMMessage.Type;
import com.easemob.chat.TextMessageBody;
import com.easemob.easeui.controller.EaseUI;
import com.easemob.easeui.controller.EaseUI.EaseSettingsProvider;
import com.easemob.easeui.controller.EaseUI.EaseUserProfileProvider;
import com.easemob.easeui.model.EaseNotifier;
import com.easemob.easeui.model.EaseNotifier.EaseNotificationInfoProvider;
import com.easemob.easeui.utils.EaseCommonUtils;
import com.easemob.easeui.utils.EaseUserUtils;
import com.easemob.exceptions.EaseMobException;
import com.easemob.util.EMLog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * im聊天工具处理
 *
 * @author seven
 */
public class IMHelper {
    /**
     * 数据同步listener
     */
    static public interface DataSyncListener {
        /**
         * 同步完毕
         *
         * @param success true：成功同步到数据，false失败
         */
        public void onSyncComplete(boolean success);
    }

    protected static final String TAG = "DemoHelper";

    private EaseUI easeUI;

    /**
     * EMEventListener
     */
    protected EMEventListener eventListener = null;

    /**
     * 联系人管理类
     */
    private UserProfileManager userProManager;

    private static IMHelper instance = null;

    private UserModel userModel = null;

    /**
     * HuanXin sync groups status listener
     */
    private List<DataSyncListener> syncGroupsListeners;
    /**
     * HuanXin sync contacts status listener
     */
    private List<DataSyncListener> syncContactsListeners;
    /**
     * HuanXin sync blacklist status listener
     */
    private List<DataSyncListener> syncBlackListListeners;

    private boolean isSyncingGroupsWithServer = false;
    private boolean isSyncingContactsWithServer = false;
    private boolean isSyncingBlackListWithServer = false;
    private boolean isGroupsSyncedWithServer = false;
    private boolean isContactsSyncedWithServer = false;
    private boolean isBlackListSyncedWithServer = false;

    private boolean alreadyNotified = false;

    public boolean isVoiceCalling;
    public boolean isVideoCalling;

    private String username;

    private Context appContext;

    private CallReceiver callReceiver;

    private EMConnectionListener connectionListener;

    private LocalBroadcastManager broadcastManager;

    private boolean isGroupAndContactListenerRegisted;
    private Handler handler;
    private ToastUtil toast;

    private IMHelper() {
    }

    public synchronized static IMHelper getInstance() {
        if (instance == null) {
            instance = new IMHelper();
        }
        return instance;
    }

    /**
     * init helper
     *
     * @param context application context
     */
    public void init(Context context) {
        if (EaseUI.getInstance().init(context)) {
            appContext = context;
            handler = new Handler(Looper.getMainLooper());
            toast = new ToastUtil(appContext);

            // if your app is supposed to user Google Push, please set project
            // number
            String projectNumber = "562451699741";
            // 不使用GCM推送的注释掉这行
            EMChatManager.getInstance().setGCMProjectNumber(projectNumber);
            // 在小米手机上当app被kill时使用小米推送进行消息提示，同GCM一样不是必须的
            EMChatManager.getInstance().setMipushConfig("2882303761517370134",
                    "5131737040134");

            // 设为调试模式，打成正式包时，最好设为false，以免消耗额外的资源
            EMChat.getInstance().setDebugMode(false);
            // get easeui instance
            easeUI = EaseUI.getInstance();
            // 调用easeui的api设置providers
            setEaseUIProviders();
            userModel = new UserModel(context);
            // 设置chat options
            setChatoptions();
            // 初始化PreferenceManager
            PreferenceManager.init(context);
            // 初始化用户管理类
            getUserProfileManager().init(context);
            // 设置全局监听
            setGlobalListeners();
            broadcastManager = LocalBroadcastManager.getInstance(appContext);
        }
    }

    /**
     * 设置聊天的选择项
     */
    private void setChatoptions() {
        // easeui库默认设置了一些options，可以覆盖
        EMChatOptions options = EMChatManager.getInstance().getChatOptions();
        options.allowChatroomOwnerLeave(getModel()
                .isChatroomOwnerLeaveAllowed());
        options.setRequireAck(false);// 设置是否需要接受方已读确认
        options.setRequireDeliveryAck(false);// 设置是否需要接受方送达确认,默认
        options.setUseRoster(false);// 不使用环信的用户体系
    }

    /**
     * 设置ui信息的提供者
     */
    protected void setEaseUIProviders() {
        // 需要easeui库显示用户头像和昵称设置此provider
        easeUI.setUserProfileProvider(new EaseUserProfileProvider() {
            @Override
            public CoworkerEntity getUser(String username) {
                return getUserInfo(username);
            }
        });

        // 不设置，则使用easeui默认的 设置
        easeUI.setSettingsProvider(new EaseSettingsProvider() {

            @Override
            public boolean isSpeakerOpened() {
                return userModel.getSettingMsgSpeaker();
            }

            @Override
            public boolean isMsgVibrateAllowed(EMMessage message) {
                return userModel.getSettingMsgVibrate();
            }

            @Override
            public boolean isMsgSoundAllowed(EMMessage message) {
                return userModel.getSettingMsgSound();
            }

            @Override
            public boolean isMsgNotifyAllowed(EMMessage message) {
                if (message == null) {
                    return userModel.getSettingMsgNotification();
                }
                if (!userModel.getSettingMsgNotification()) {
                    return false;
                } else {
                    return true;
                }
            }
        });
        // 离线提示消息
        // 不设置，则使用easeui默认的
        easeUI.getNotifier().setNotificationInfoProvider(
                new EaseNotificationInfoProvider() {

                    @Override
                    public String getTitle(EMMessage message) {
                        // 修改标题,这里使用默认
                        return null;
                    }

                    @Override
                    public int getSmallIcon(EMMessage message) {
                        // 设置小图标，这里为默认
                        return 0;
                    }

                    @Override
                    public String getDisplayedText(EMMessage message) {
                        // 设置状态栏的消息提示，可以根据message的类型做相应提示
                        String ticker = EaseCommonUtils.getMessageDigest(
                                message, appContext);
                        if (message.getType() == Type.TXT) {
                            ticker = ticker.replaceAll("\\[.{2,3}\\]", "[表情]");
                        }
                        String userNick = EaseUserUtils.getUserNick(message);
                        return userNick + ": " + ticker;
                    }

                    @Override
                    public String getLatestText(EMMessage message,
                                                int fromUsersNum, int messageNum) {
                        return null;
                        // return fromUsersNum + "个基友，发来了" + messageNum + "条消息";
                    }

                    @Override
                    public Intent getLaunchIntent(EMMessage message) {
                        // 设置点击通知栏跳转事件
                        Intent intent = new Intent(appContext,
                                ChatActivity.class);
                        // 有电话时优先跳转到通话页面
                        if (isVideoCalling) {
                            intent = new Intent(appContext,
                                    VideoCallActivity.class);
                        } else if (isVoiceCalling) {
                            intent = new Intent(appContext,
                                    VoiceCallActivity.class);
                        } else {
                            // 普通消息的时候 首先判断是不是在前台 如果 在前台 就打开聊天页面 如果不再前台 就先打开
                            boolean hasForegroundActivies = AppManager
                                    .getInstance().hasForegroundActivies();
                            if (!hasForegroundActivies) {// 不是前台 先进入首页
                                intent = new Intent(appContext,
                                        WelcomeActivity.class);
                            }
                            ChatType chatType = message.getChatType();
                            if (chatType == ChatType.Chat) { // 单聊信息
                                intent.putExtra("userId", message.getFrom());
                                intent.putExtra("chatType",
                                        Constant.CHATTYPE_SINGLE);
                            } else { // 群聊信息
                                // message.getTo()为群聊id
                                intent.putExtra("userId", message.getTo());
                                if (chatType == ChatType.GroupChat) {
                                    intent.putExtra("chatType",
                                            Constant.CHATTYPE_GROUP);
                                } else {
                                    intent.putExtra("chatType",
                                            Constant.CHATTYPE_CHATROOM);
                                }

                            }
                        }
                        return intent;
                    }
                });
    }

    /**
     * 设置全局事件监听
     */
    protected void setGlobalListeners() {
        syncGroupsListeners = new ArrayList<DataSyncListener>();
        syncContactsListeners = new ArrayList<DataSyncListener>();
        syncBlackListListeners = new ArrayList<DataSyncListener>();

        isGroupsSyncedWithServer = userModel.isGroupsSynced();
        isContactsSyncedWithServer = userModel.isContactSynced();
        isBlackListSyncedWithServer = userModel.isBacklistSynced();

        // create the global connection listener
        connectionListener = new EMConnectionListener() {
            @Override
            public void onDisconnected(int error) {
                LogUtils.d("imchat", "服务器断开了:" + error);
                if (error == EMError.USER_REMOVED) {
                    onCurrentAccountRemoved();
                } else if (error == EMError.CONNECTION_CONFLICT) {
                    LogUtils.d("imchat", "单点登录。。。。");
                    if (!"cc201307019DXlPd701".equals(RunTimeManager.getInstance().getOrgId())) {
                        onConnectionConflict();
                    }
                }
            }

            @Override
            public void onConnected() {
                LogUtils.d("imchat", "连接上服务器了:isGroupsSyncedWithServer:"
                        + isGroupsSyncedWithServer
                        + " isContactsSyncedWithServer: "
                        + isContactsSyncedWithServer);
                // in case group and contact were already synced, we supposed to
                // notify sdk we are ready to receive the events
                if (isGroupsSyncedWithServer && isContactsSyncedWithServer) {
                    new Thread() {
                        @Override
                        public void run() {
                            IMHelper.getInstance().notifyForRecevingEvents();
                        }
                    }.start();
                } else {
                    if (!isGroupsSyncedWithServer) {
                        asyncFetchGroupsFromServer(null);
                    }

                    if (!isContactsSyncedWithServer) {
                        asyncFetchContactsFromServer(null);
                    }

                    // 黑名单
                    // if (!isBlackListSyncedWithServer) {
                    // asyncFetchBlackListFromServer(null);
                    // }
                }
            }
        };

        IntentFilter callFilter = new IntentFilter(EMChatManager.getInstance()
                .getIncomingCallBroadcastAction());
        if (callReceiver == null) {
            callReceiver = new CallReceiver();
        }

        // 注册通话广播接收者
        appContext.registerReceiver(callReceiver, callFilter);
        // 注册连接监听
        EMChatManager.getInstance().addConnectionListener(connectionListener);
        // 注册群组和联系人监听
        registerGroupAndContactListener();
        // 注册消息事件监听
        registerEventListener();

    }

    /**
     * 注册群组和联系人监听，由于logout的时候会被sdk清除掉，再次登录的时候需要再注册一下
     */
    public void registerGroupAndContactListener() {
        if (!isGroupAndContactListenerRegisted) {
            // 注册群组变动监听
            EMGroupManager.getInstance().addGroupChangeListener(
                    new MyGroupChangeListener());
            isGroupAndContactListenerRegisted = true;
        }

    }

    /**
     * 群组变动监听
     */
    class MyGroupChangeListener implements EMGroupChangeListener {

        @Override
        public void onInvitationReceived(String groupId, final String groupName,
                                         String inviter, String reason) {

            boolean hasGroup = false;
            for (EMGroup group : EMGroupManager.getInstance().getAllGroups()) {
                if (group.getGroupId().equals(groupId)) {
                    hasGroup = true;
                    break;
                }
            }
            if (!hasGroup)
                return;

            // 被邀请
            String st3 = appContext
                    .getString(R.string.Invite_you_to_join_a_group_chat);
            EMMessage msg = EMMessage.createReceiveMessage(Type.TXT);
            msg.setChatType(ChatType.GroupChat);
            msg.setFrom(inviter);
            msg.setTo(groupId);
            msg.setMsgId(UUID.randomUUID().toString());
            msg.addBody(new TextMessageBody(st3));
            // 保存邀请消息
            EMChatManager.getInstance().saveMessage(msg);
            // 提醒新消息
            getNotifier().viberateAndPlayTone(msg);
            // 发送local广播
            broadcastManager.sendBroadcast(new Intent(
                    Constant.ACTION_GROUP_CHANAGED));
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast.setTextNoImage(appContext.getString(R.string.yunxinmessageyaoqing) + groupName).Short(appContext, "").show(30, appContext);
                }
            });

        }

        @Override
        public void onInvitationAccpted(String groupId, String inviter,
                                        String reason) {
        }

        @Override
        public void onInvitationDeclined(String groupId, String invitee,
                                         String reason) {
        }

        @Override
        public void onUserRemoved(String groupId, final String groupName) {
            // TODO 提示用户被T了，demo省略此步骤
            broadcastManager.sendBroadcast(new Intent(
                    Constant.ACTION_GROUP_CHANAGED));
            handler.post(new Runnable() {
                @Override
                public void run() {
                    toast.setTextNoImage(appContext.getString(R.string.yunxinmessageyichu) + groupName).Short(appContext, "").show(30, appContext);
                }
            });
        }

        @Override
        public void onGroupDestroy(String groupId, String groupName) {
            // 群被解散
            // TODO 提示用户群被解散,demo省略
            broadcastManager.sendBroadcast(new Intent(
                    Constant.ACTION_GROUP_CHANAGED));
        }

        @Override
        public void onApplicationReceived(String groupId, String groupName,
                                          String applyer, String reason) {

            // 用户申请加入群聊
            InviteMessage msg = new InviteMessage();
            msg.setFrom(applyer);
            msg.setTime(System.currentTimeMillis());
            msg.setGroupId(groupId);
            msg.setGroupName(groupName);
            msg.setReason(reason);
            Log.d(TAG, applyer + " 申请加入群聊：" + groupName);
            msg.setStatus(InviteMesageStatus.BEAPPLYED);
            notifyNewIviteMessage(msg);
            broadcastManager.sendBroadcast(new Intent(
                    Constant.ACTION_GROUP_CHANAGED));
        }

        @Override
        public void onApplicationAccept(String groupId, String groupName,
                                        String accepter) {

            String st4 = appContext
                    .getString(R.string.Agreed_to_your_group_chat_application);
            // 加群申请被同意
            EMMessage msg = EMMessage.createReceiveMessage(Type.TXT);
            msg.setChatType(ChatType.GroupChat);
            msg.setFrom(accepter);
            msg.setTo(groupId);
            msg.setMsgId(UUID.randomUUID().toString());
            msg.addBody(new TextMessageBody(accepter + " " + st4));
            // 保存同意消息
            EMChatManager.getInstance().saveMessage(msg);
            // 提醒新消息
            getNotifier().viberateAndPlayTone(msg);
            broadcastManager.sendBroadcast(new Intent(
                    Constant.ACTION_GROUP_CHANAGED));
        }

        @Override
        public void onApplicationDeclined(String groupId, String groupName,
                                          String decliner, String reason) {
            // 加群申请被拒绝，demo未实现
        }
    }

    /**
     * 保存并提示消息的邀请消息
     *
     * @param msg
     */
    private void notifyNewIviteMessage(InviteMessage msg) {
        // 提示有新消息
        getNotifier().viberateAndPlayTone(null);
    }

    /**
     * 账号在别的设备登录
     */
    protected void onConnectionConflict() {
        Intent intent = new Intent(appContext, ConversationListActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(Constant.ACCOUNT_CONFLICT, true);
        appContext.startActivity(intent);
    }

    /**
     * TODO IM 修改 账号被移除的时候
     */
    protected void onCurrentAccountRemoved() {
        Intent intent = new Intent(appContext, MainUIActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(Constant.ACCOUNT_REMOVED, true);
        appContext.startActivity(intent);
    }

    private CoworkerEntity getUserInfo(String hxUserName) {
        // 获取user信息，demo是从内存的好友列表里获取，
        // 实际开发中，可能还需要从服务器获取用户信息,
        // 从服务器获取的数据，最好缓存起来，避免频繁的网络请求
        CoworkerEntity user = null;
        // if(username.equals(EMChatManager.getInstance().getCurrentUser()))
        // return getUserProfileManager().getCurrentUserInfo();
        user = ContactsManager.getInstance().getUserInfoByHXId(hxUserName);
        // TODO 获取不在好友列表里的群成员具体信息，即陌生人信息，demo未实现
        // if(user == null && getRobotList() != null){
        // user = getRobotList().get(username);
        // }
        // 如果获得的为空 就去同步通讯录
        return user;
    }

    /**
     * 全局事件监听 因为可能会有UI页面先处理到这个消息，所以一般如果UI页面已经处理，这里就不需要再次处理 activityList.size()
     * <= 0 意味着所有页面都已经在后台运行，或者已经离开Activity Stack
     */
    protected void registerEventListener() {
        eventListener = new EMEventListener() {
            private BroadcastReceiver broadCastReceiver = null;

            @Override
            public void onEvent(EMNotifierEvent event) {
                LogUtils.d("imchat",
                        "收到消息,是否在前台" + easeUI.hasForegroundActivies());

                EMMessage message = null;
                if (event.getData() instanceof EMMessage) {
                    message = (EMMessage) event.getData();
                    EMLog.d(TAG, "receive the event : " + event.getEvent()
                            + ",id : " + message.getMsgId());
                }

                switch (event.getEvent()) {
                    case EventNewMessage:
                        // 应用在后台，不需要刷新UI,通知栏提示新消息

                        if (!easeUI.hasForegroundActivies()) {
                            getNotifier().onNewMsg(message);
                        }
                        break;
                    case EventOfflineMessage:
                        if (!easeUI.hasForegroundActivies()) {
                            EMLog.d(TAG, "received offline messages");
                            List<EMMessage> messages = (List<EMMessage>) event
                                    .getData();
                            getNotifier().onNewMesg(messages);
                        }
                        break;
                    // below is just giving a example to show a cmd toast, the app
                    // should not follow this
                    // so be careful of this
                    case EventNewCMDMessage: {

                        EMLog.d(TAG, "收到透传消息");
                        // 获取消息body
                        CmdMessageBody cmdMsgBody = (CmdMessageBody) message
                                .getBody();
                        final String action = cmdMsgBody.action;// 获取自定义action

                        // 获取扩展属性 此处省略
                        // message.getStringAttribute("");
                        EMLog.d(TAG, String.format("透传消息：action:%s,message:%s",
                                action, message.toString()));
                        final String str = appContext
                                .getString(R.string.receive_the_passthrough);

                        final String CMD_TOAST_BROADCAST = "easemob.demo.cmd.toast";
                        IntentFilter cmdFilter = new IntentFilter(
                                CMD_TOAST_BROADCAST);

                        if (broadCastReceiver == null) {
                            broadCastReceiver = new BroadcastReceiver() {

                                @Override
                                public void onReceive(Context context, Intent intent) {
                                    // TODO Auto-generated method stub
                                    Toast.makeText(appContext,
                                            intent.getStringExtra("cmd_value"),
                                            Toast.LENGTH_SHORT).show();
                                }
                            };

                            // 注册广播接收者
                            appContext.registerReceiver(broadCastReceiver,
                                    cmdFilter);
                        }

                        Intent broadcastIntent = new Intent(CMD_TOAST_BROADCAST);
                        broadcastIntent.putExtra("cmd_value", str + action);
                        appContext.sendBroadcast(broadcastIntent, null);

                        break;
                    }
                    case EventDeliveryAck:
                        message.setDelivered(true);
                        break;
                    case EventReadAck:
                        message.setAcked(true);
                        break;
                    // add other events in case you are interested in
                    default:
                        break;
                }

            }
        };

        EMChatManager.getInstance().registerEventListener(eventListener);
    }

    /**
     * 是否登录成功过
     *
     * @return
     */
    public boolean isLoggedIn() {
        return EMChat.getInstance().isLoggedIn();
    }

    /**
     * 退出登录
     *
     * @param unbindDeviceToken 是否解绑设备token(使用GCM才有)
     * @param callback          callback
     */
    public void logout(boolean unbindDeviceToken, final EMCallBack callback) {
        endCall();
        EMChatManager.getInstance().logout(unbindDeviceToken, new EMCallBack() {

            @Override
            public void onSuccess() {
                reset();
                if (callback != null) {
                    callback.onSuccess();
                }

            }

            @Override
            public void onProgress(int progress, String status) {
                if (callback != null) {
                    callback.onProgress(progress, status);
                }
            }

            @Override
            public void onError(int code, String error) {
                if (callback != null) {
                    callback.onError(code, error);
                }
            }
        });
    }

    /**
     * 获取消息通知类
     *
     * @return
     */
    public EaseNotifier getNotifier() {
        return easeUI.getNotifier();
    }

    public UserModel getModel() {
        return (UserModel) userModel;
    }

    /**
     * 获取好友list
     *
     * @return
     */
    public Map<String, CoworkerEntity> getContactList() {
        return ContactsManager.getInstance().getContactList();
    }

    /**
     * 设置当前用户的环信id
     *
     * @param username
     */
    public void setCurrentUserName(String username) {
        this.username = username;
        userModel.setCurrentUserName(username);
    }

    /**
     * 获取当前用户的环信id
     */
    public String getCurrentUsernName() {
        if (username == null) {
            username = userModel.getCurrentUsernName();
        }
        return username;
    }

    public UserProfileManager getUserProfileManager() {
        if (userProManager == null) {
            userProManager = new UserProfileManager();
        }
        return userProManager;
    }

    void endCall() {
        try {
            EMChatManager.getInstance().endCall();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void addSyncGroupListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (!syncGroupsListeners.contains(listener)) {
            syncGroupsListeners.add(listener);
        }
    }

    public void removeSyncGroupListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (syncGroupsListeners.contains(listener)) {
            syncGroupsListeners.remove(listener);
        }
    }

    public void addSyncContactListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (!syncContactsListeners.contains(listener)) {
            syncContactsListeners.add(listener);
        }
    }

    public void removeSyncContactListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (syncContactsListeners.contains(listener)) {
            syncContactsListeners.remove(listener);
        }
    }

    public void addSyncBlackListListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (!syncBlackListListeners.contains(listener)) {
            syncBlackListListeners.add(listener);
        }
    }

    public void removeSyncBlackListListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (syncBlackListListeners.contains(listener)) {
            syncBlackListListeners.remove(listener);
        }
    }

    /**
     * 同步操作，从服务器获取群组列表 该方法会记录更新状态，可以通过isSyncingGroupsFromServer获取是否正在更新
     * 和isGroupsSyncedWithServer获取是否更新已经完成
     *
     * @throws EaseMobException
     */
    public synchronized void asyncFetchGroupsFromServer(
            final EMCallBack callback) {
        if (isSyncingGroupsWithServer) {
            return;
        }

        isSyncingGroupsWithServer = true;

        new Thread() {
            @Override
            public void run() {
                try {
                    EMGroupManager.getInstance().getGroupsFromServer();

                    // in case that logout already before server returns, we
                    // should return immediately
                    if (!EMChat.getInstance().isLoggedIn()) {
                        return;
                    }

                    userModel.setGroupsSynced(true);

                    isGroupsSyncedWithServer = true;
                    isSyncingGroupsWithServer = false;

                    // 通知listener同步群组完毕
                    noitifyGroupSyncListeners(true);
                    if (isContactsSyncedWithServer()) {
                        notifyForRecevingEvents();
                    }
                    if (callback != null) {
                        callback.onSuccess();
                    }
                } catch (EaseMobException e) {
                    userModel.setGroupsSynced(false);
                    isGroupsSyncedWithServer = false;
                    isSyncingGroupsWithServer = false;
                    noitifyGroupSyncListeners(false);
                    if (callback != null) {
                        callback.onError(e.getErrorCode(), e.toString());
                    }
                }

            }
        }.start();
    }

    public void noitifyGroupSyncListeners(boolean success) {
        for (DataSyncListener listener : syncGroupsListeners) {
            listener.onSyncComplete(success);
        }
    }

    public void asyncFetchContactsFromServer(
            final EMValueCallBack<List<String>> callback) {
        LogUtils.d("imchat", "环信同步联系人");
        if (isSyncingContactsWithServer) {
            return;
        }

        isSyncingContactsWithServer = true;

        new Thread() {
            @Override
            public void run() {
                List<String> usernames = null;
                try {
                    usernames = EMContactManager.getInstance()
                            .getContactUserNames();
                    // in case that logout already before server returns, we
                    // should return immediately
                    if (!EMChat.getInstance().isLoggedIn()) {
                        return;
                    }

                    Map<String, CoworkerEntity> userlist = new HashMap<String, CoworkerEntity>();
                    for (String username : usernames) {
                        CoworkerEntity user = new CoworkerEntity();
                        // EaseCommonUtils.setUserInitialLetter(user);
                        userlist.put(username, user);
                    }
                    // 存入内存
                    getContactList().clear();
                    getContactList().putAll(userlist);
                    // 存入db
                    // UserDao dao = new UserDao(appContext);
                    List<CoworkerEntity> users = new ArrayList<CoworkerEntity>(
                            userlist.values());
                    // dao.saveContactList(users);

                    userModel.setContactSynced(true);
                    EMLog.d(TAG, "set contact syn status to true");

                    isContactsSyncedWithServer = true;
                    isSyncingContactsWithServer = false;

                    // 通知listeners联系人同步完毕
                    notifyContactsSyncListener(true);
                    if (isGroupsSyncedWithServer()) {
                        notifyForRecevingEvents();
                    }

                    // test
                    // getUserProfileManager().asyncFetchContactInfosFromServer(usernames,new
                    // EMValueCallBack<List<SortModel>>() {
                    //
                    // @Override
                    // public void onSuccess(List<SortModel> uList) {
                    // updateContactList(uList);
                    // getUserProfileManager().notifyContactInfosSyncListener(true);
                    // }
                    //
                    // @Override
                    // public void onError(int error, String errorMsg) {
                    // }
                    // });
                    if (callback != null) {
                        callback.onSuccess(usernames);
                    }
                } catch (EaseMobException e) {
                    userModel.setContactSynced(false);
                    isContactsSyncedWithServer = false;
                    isSyncingContactsWithServer = false;
                    noitifyGroupSyncListeners(false);
                    e.printStackTrace();
                    if (callback != null) {
                        callback.onError(e.getErrorCode(), e.toString());
                    }
                }

            }
        }.start();
    }

    public void notifyContactsSyncListener(boolean success) {
        for (DataSyncListener listener : syncContactsListeners) {
            listener.onSyncComplete(success);
        }
    }

    public void asyncFetchBlackListFromServer(
            final EMValueCallBack<List<String>> callback) {

        if (isSyncingBlackListWithServer) {
            return;
        }

        isSyncingBlackListWithServer = true;

        new Thread() {
            @Override
            public void run() {
                try {
                    List<String> usernames = EMContactManager.getInstance()
                            .getBlackListUsernamesFromServer();

                    // in case that logout already before server returns, we
                    // should return immediately
                    if (!EMChat.getInstance().isLoggedIn()) {
                        return;
                    }

                    userModel.setBlacklistSynced(true);

                    isBlackListSyncedWithServer = true;
                    isSyncingBlackListWithServer = false;

                    EMContactManager.getInstance().saveBlackList(usernames);
                    notifyBlackListSyncListener(true);
                    if (callback != null) {
                        callback.onSuccess(usernames);
                    }
                } catch (EaseMobException e) {
                    userModel.setBlacklistSynced(false);

                    isBlackListSyncedWithServer = false;
                    isSyncingBlackListWithServer = true;
                    e.printStackTrace();

                    if (callback != null) {
                        callback.onError(e.getErrorCode(), e.toString());
                    }
                }

            }
        }.start();
    }

    public void notifyBlackListSyncListener(boolean success) {
        for (DataSyncListener listener : syncBlackListListeners) {
            listener.onSyncComplete(success);
        }
    }

    public boolean isSyncingGroupsWithServer() {
        return isSyncingGroupsWithServer;
    }

    public boolean isSyncingContactsWithServer() {
        return isSyncingContactsWithServer;
    }

    public boolean isSyncingBlackListWithServer() {
        return isSyncingBlackListWithServer;
    }

    public boolean isGroupsSyncedWithServer() {
        return isGroupsSyncedWithServer;
    }

    public boolean isContactsSyncedWithServer() {
        return isContactsSyncedWithServer;
    }

    public boolean isBlackListSyncedWithServer() {
        return isBlackListSyncedWithServer;
    }

    public synchronized void notifyForRecevingEvents() {
        if (alreadyNotified) {
            return;
        }
        // 通知sdk，UI 已经初始化完毕，注册了相应的receiver和listener, 可以接受broadcast了
        EMChat.getInstance().setAppInited();
        alreadyNotified = true;
    }

    synchronized void reset() {
        isSyncingGroupsWithServer = false;
        isSyncingContactsWithServer = false;
        isSyncingBlackListWithServer = false;

        userModel.setGroupsSynced(false);
        userModel.setContactSynced(false);
        userModel.setBlacklistSynced(false);

        isGroupsSyncedWithServer = false;
        isContactsSyncedWithServer = false;
        isBlackListSyncedWithServer = false;

        alreadyNotified = false;
        isGroupAndContactListenerRegisted = false;

        getUserProfileManager().reset();
    }

    public void pushActivity(Activity activity) {
        easeUI.pushActivity(activity);
    }

    public void popActivity(Activity activity) {
        easeUI.popActivity(activity);
    }

}
